﻿using MesGLApp.BLL;
using MesGLApp.DAL.MesDB;
using MesGLApp.DAL.MesDTO;
using MesGLApp.Tools;
using MesGLApp.View;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Gl_mes.BLL.Mes
{
    public class ProdProcessControler : BaseControler
    {
        public SiteInfo SearchFirstSiteForSiteGroup(int groupID)
        {
            SiteInfo siteInfo = new SiteInfo();
            using (MesDB ctx = new MesDB())
            {
                var query = from a in ctx.SiteGroups
                            join b in ctx.SiteInfoGroups on a.ID equals b.GroupID
                            join c in ctx.SiteInfos on b.SiteID equals c.ID
                            where a.ID == groupID && b.Sort == 1
                            select c;
                if (query != null && query.Count() > 0)
                {
                    siteInfo = query.First();
                }
            }
            return siteInfo;
        }


        /// <summary>
        /// 查询所有站点组别
        /// </summary>
        /// <returns></returns>
        public List<SiteGroup> SearchAllSiteGroup()
        {
            List<SiteGroup> resList = new List<SiteGroup>();
            using (MesDB ctx = new MesDB())
            {
                var query = ctx.SiteGroups;
                if (query != null && query.Count() > 0)
                {
                    resList.AddRange(query);
                }
            }
            return resList;
        }


        public SourceProdProcess SearchSourcePPForProdNo(string prodNo)
        {
            SourceProdProcess resBean = new SourceProdProcess();
            using (MesDB ctx = new MesDB())
            {
                var query = ctx.SourceProdProcesses.Where(s => s.ProdNumber.Equals(prodNo));
                if (query != null && query.Count() > 0)
                {
                    resBean = query.First();    
                }
            }
            return resBean;
        }

        public TargetProdProcessDTO SearchTargetPPForProdNo(string prodNo)
        {
            TargetProdProcessDTO resBean = new TargetProdProcessDTO();
            using (MesDB ctx = new MesDB())
            {
                var targetQuery = from a in ctx.TargetProdProcesses
                                  join b in ctx.ProdProcSites on a.ID equals b.ProdProcID into res
                                  from ab in res.DefaultIfEmpty()
                                  join c in ctx.SiteGroups on ab.SiteGroupID equals c.ID into res1
                                  from bc in res1.DefaultIfEmpty()
                                  where a.ProdNumber.Equals(prodNo)
                                  select new { A = a, B = ab, C = bc };
                if (targetQuery != null && targetQuery.Count() > 0)
                {
                    EntityTools.CopyEntity(targetQuery.First().A, ref resBean);
                    SiteGroupDTO site = new SiteGroupDTO();
                    if (targetQuery.First().B != null)
                    {
                        EntityTools.CopyEntity(targetQuery.First().C, ref site);
                        resBean.SiteGroup = site;
                    }
                }
            }
            return resBean;
        }

        public TargetPPCycle SearchTargetCycleByProdNo(string prodNo)
        {
            TargetPPCycle resBean = new TargetPPCycle();
            using (MesDB ctx = new MesDB())
            {
                var query = ctx.TargetPPCycle.Where(t => t.ProdNumber.Equals(prodNo));
                if (query != null && query.Count() > 0)
                {
                    resBean = query.First();
                }
            }
            return resBean;
        }


        /// <summary>
        /// 根据工单号查询原料工单和拆分后的工单资料
        /// </summary>
        /// <param name="billno"></param>
        /// <returns></returns>
        public SourceProdProcessDTO SearchProdProcessByBillNo(string billno)
        {
            SourceProdProcessDTO resBean = new SourceProdProcessDTO();
            using (MesDB ctx = new MesDB())
            {
                //查询原始工单
                var query = ctx.SourceProdProcesses.Where(s => s.ProdNumber == billno);
                if (query != null && query.Count() > 0)
                {
                    EntityTools.CopyEntity<SourceProdProcess,SourceProdProcessDTO>(query.First<SourceProdProcess>(),ref resBean);
                    if (resBean != null)
                    {
                        //如果原始工单已经录入到MES系统中，继续查找是否有拆分单据
                        var targetQuery = from a in ctx.TargetProdProcesses
                                          join b in ctx.ProdProcSites on a.ID equals b.ProdProcID into res
                                          from ab in res.DefaultIfEmpty()
                                          join c in ctx.SiteGroups on ab.SiteGroupID equals c.ID into res1
                                          from bc in res1.DefaultIfEmpty()
                                          where a.ParentID == resBean.ID
                                          select new { A = a, B = ab, C = bc };
                        resBean.targetList = new List<TargetProdProcessDTO>();
                        if (targetQuery != null && targetQuery.Count() > 0)
                        {
                            foreach (var item in targetQuery)
                            {
                                TargetProdProcessDTO target = new TargetProdProcessDTO();
                                EntityTools.CopyEntity(item.A,ref target);
                                SiteGroupDTO site = new SiteGroupDTO();
                                if (item.B != null)
                                {
                                    EntityTools.CopyEntity(item.C,ref site);
                                    target.SiteGroup = site;
                                }
                                resBean.targetList.Add(target);
                            }
                        }
                    }
                }
            }
            return resBean;
        }


        public TargetProdProcess SearchTargetProdProcessByPordNumber(string prodNumber)
        {
            using (MesDB ctx = new MesDB())
            {
                var query = ctx.TargetProdProcesses.Where(p => p.ProdNumber == prodNumber);
                if (query != null && query.Count() > 0)
                {
                    return query.First<TargetProdProcess>();
                }
                else
                {
                    return null;
                }
            }
        }


        public int SaveProdProcessForFirstScan(ProdProcScan scan)
        {
            int count = 0;
            if (scan != null)
            {
                using (MesDB ctx = new MesDB())
                {
                    var scanQuery = from a in ctx.ProdProcScans
                                    join b in ctx.SiteInfos on a.SiteInfoID equals b.ID into res1
                                    from ab in res1.DefaultIfEmpty()
                                    join c in ctx.TargetProdProcesses on a.ProdProcID equals c.ID into res2
                                    from ac in res2.DefaultIfEmpty()
                                    join d in ctx.StatusInfos on a.StatusInfoID equals d.ID into res3
                                    from ad in res3.DefaultIfEmpty()
                                    where a.ProdProcID == scan.ProdProcID && a.SiteInfoID == scan.SiteInfoID
                                    where ad.StatusValue.Contains("异常") == false
                                    select new { A = a, AB = ab, AC = ac, AD = ad};
                    if (scanQuery != null && scanQuery.Count() > 0)
                    {
                        throw new Exception("工单：" + scanQuery.First().AC.ProdNumber + "\r\n" +
                                                "站点：" + scanQuery.First().AB.SiteName + "\r\n" + "该站点已扫过码！");
                    }
                    else
                    {
                        scan.ScanUser = LoginFrm.LoginUser.user_name;
                        scan.ScanDate = GetCurrDateTime();
                        ctx.ProdProcScans.Add(scan);
                        count = ctx.SaveChanges();
                        return count;
                    }
                }
            }
            else
            {
                throw new Exception("传入的扫码资料为空，扫码失败！");
            }
        }


        /// <summary>
        /// 保存拆分工单
        /// </summary>
        /// <param name="sourcePP"></param>
        /// <param name="copyPP"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public int SaveProdProcessForSplit(SourceProdProcessDTO sourcePP,SourceProdProcessDTO copyPP)
        {
            int count = 0;
            if (sourcePP != null)
            {
                using (MesDB ctx = new MesDB())
                {
                    //打开事务
                    using (var tran = ctx.Database.BeginTransaction())
                    {
                        try 
                        {
                            //先保存原工单资料
                            SourceProdProcess spp = new SourceProdProcess();
                            EntityTools.CopyEntity<SourceProdProcessDTO, SourceProdProcess>(sourcePP, ref spp);
                            int sppID = 0;
                            if (sourcePP.ID == 0)
                            {
                                //如果原工单的ID主键为0，使用新增操作
                                spp.CreateUser = LoginFrm.LoginUser.user_name;
                                spp.CreateDate = DateTime.Now;
                                ctx.SourceProdProcesses.Add(spp);
                            }
                            else if (sourcePP.ID > 0)
                            {
                                SourceProdProcess tmpSpp = new SourceProdProcess();
                                EntityTools.CopyEntity<SourceProdProcessDTO, SourceProdProcess>(copyPP,ref tmpSpp);
                                //如果原工单的ID主键不为0，使用更新操作
                                if (EntityTools.IsDiffForValue(spp, tmpSpp) == false)
                                {
                                    //更新操作时，保存一份日志
                                    MesLog tmpBean = this.InitMesLog("source_prod_precess", sourcePP.ID, EntityTools.GetPropNameAndValue(tmpSpp), 
                                                                        EntityTools.GetPropNameAndValue(sourcePP),"update", LoginFrm.LoginUser.user_name);
                                    ctx.MesLogs.Add(tmpBean);

                                    //更改实体类的状态
                                    ctx.SourceProdProcesses.Attach(spp);
                                    ctx.Entry<SourceProdProcess>(spp).State = System.Data.Entity.EntityState.Modified;
                                }
                            }
                            //保存原工单，并取得保存后数据库分配的ID主键
                            count += ctx.SaveChanges();
                            sppID = spp.ID;

                            //开始保存拆分后的工单
                            if (sourcePP.targetList != null && sourcePP.targetList.Count > 0)
                            {
                                foreach (var item in sourcePP.targetList)
                                {
                                    TargetProdProcess tpp = new TargetProdProcess();
                                    EntityTools.CopyEntity<TargetProdProcessDTO, TargetProdProcess>(item, ref tpp);
                                    
                                    if (item.ID == 0)
                                    {
                                        //如果拆分工单的ID为0
                                        //使用新增操作保存拆分工单
                                        tpp.ParentID = sppID;
                                        tpp.CreateDate = DateTime.Now;
                                        tpp.CreateUser = LoginFrm.LoginUser.user_name;
                                        ctx.TargetProdProcesses.Add(tpp);
                                        count += ctx.SaveChanges();

                                        //因为拆分工单是新增，所以拆分工单与站点组的绑定也是新增操作
                                        ProdProcSite PPsite = new ProdProcSite();
                                        PPsite.ProdProcID = tpp.ID;
                                        PPsite.SiteGroupID = item.SiteGroup.ID;
                                        PPsite.CreateDate = DateTime.Now;
                                        PPsite.CreateUser = LoginFrm.LoginUser.user_name;
                                        ctx.ProdProcSites.Add(PPsite);
                                        count += ctx.SaveChanges();
                                    }
                                    else if (item.ID > 0)
                                    {
                                        //如果拆分工单的ID不为0，证明拆分工单资料已经存在于数据库，先按ID在数据库中获取拆分工单资料
                                        TargetProdProcess tmpTpp = new TargetProdProcess();
                                        if (copyPP != null && copyPP.targetList != null && copyPP.targetList.Count > 0)
                                        {
                                            var tppQuery = copyPP.targetList.Where(t => t.ID == item.ID);
                                            if (tppQuery != null && tppQuery.Count() > 0)
                                            {
                                                EntityTools.CopyEntity(tppQuery.First(),ref tmpTpp);
                                            }
                                        }

                                        //对比资料，如果资料对不上，使用更新操作保存拆分工单
                                        if (EntityTools.IsDiffForValue(tmpTpp, tpp) == false)
                                        {
                                            //保存更新拆分工单的日志
                                            MesLog tmpBean = this.InitMesLog("target_prod_precess", item.ID, EntityTools.GetPropNameAndValue(tmpTpp), 
                                                                                EntityTools.GetPropNameAndValue(tpp), "update", LoginFrm.LoginUser.user_name);
                                            ctx.MesLogs.Add(tmpBean);

                                            //更改拆分工单的状态，准备更新操作
                                            ctx.Set<TargetProdProcess>().Attach(tpp);
                                            ctx.Entry<TargetProdProcess>(tpp).State = System.Data.Entity.EntityState.Modified;
                                        }
                                        count += ctx.SaveChanges();

                                        //查询拆分工单与站点组原来的绑定状态
                                        var siteQuery = ctx.ProdProcSites.Where(ps => ps.ProdProcID == item.ID);
                                        if (siteQuery != null && siteQuery.Count() > 0)
                                        {
                                            //如果有已有绑定状态，检查原来绑定的站点组与现在绑定的站点组ID是否一致，不致的就更新绑定状态，并保留日志
                                            if (siteQuery.First().SiteGroupID != item.SiteGroup.ID)
                                            {
                                                MesLog tmpBean1 = new MesLog();
                                                tmpBean1.TableName = "pp_site";
                                                tmpBean1.TableID = siteQuery.First().ID;
                                                tmpBean1.BeforeData = EntityTools.GetPropNameAndValue(siteQuery.First());
                                                tmpBean1.AfterData = EntityTools.GetPropNameAndValue(item.ProdStatus);
                                                tmpBean1.ChangeType = "update";
                                                tmpBean1.ChangeDate = DateTime.Now;
                                                tmpBean1.ChangeUser = LoginFrm.LoginUser.user_name;
                                                ctx.MesLogs.Add(tmpBean1);

                                                ctx.ProdProcSites.Attach(siteQuery.First());
                                                ctx.Entry<ProdProcSite>(siteQuery.First()).State = System.Data.Entity.EntityState.Modified;
                                            }
                                        }
                                        else
                                        {
                                            //如果没有绑定状态，新增
                                            ProdProcSite PPsite = new ProdProcSite();
                                            PPsite.ProdProcID = item.ID;
                                            PPsite.SiteGroupID = item.SiteGroup.ID;
                                            PPsite.CreateDate = DateTime.Now;
                                            PPsite.CreateUser = LoginFrm.LoginUser.user_name;
                                            ctx.ProdProcSites.Add(PPsite);
                                        }
                                        count += ctx.SaveChanges();
                                    }

                                    var query = ctx.TargetPPCycle.Where(t => t.ProdNumber == item.ProdNumber);
                                    if (query == null || query.Count() <= 0)
                                    { 
                                        TargetPPCycle tmpCycle = new TargetPPCycle();
                                        tmpCycle.ID = 0;
                                        tmpCycle.TargetID = tpp.ID;
                                        tmpCycle.ProdNumber = item.ProdNumber;
                                        tmpCycle.CreateUser = LoginFrm.LoginUser.user_name;
                                        tmpCycle.CreateDate = GetCurrDateTime();

                                        ctx.TargetPPCycle.Add(tmpCycle);

                                        count += ctx.SaveChanges();
                                    }
                                }
                            }
                            tran.Commit();
                            return count;
                        }
                        catch (Exception ex)
                        {
                            tran.Rollback();
                            throw ex;
                        }
                    }
                }
            }
            else
            {
                throw new Exception("传入的工单对像为空，中止保存！");
            }
        }


        /// <summary>
        /// 删除拆分工单
        /// </summary>
        /// <param name="targetID"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public int DeleteTargetProdProcess(int targetID)
        {
            int count = 0;
            using (MesDB ctx = new MesDB())
            {
                var scanQuery = ctx.ProdProcScans.Where(s => s.ProdProcID == targetID);
                if (scanQuery != null && scanQuery.Count() > 0)
                {
                    throw new Exception("工单已经开始扫码，不能删除！");
                }
                else
                {
                    var siteQuery = ctx.ProdProcSites.Where(s => s.ProdProcID == targetID);
                    if (siteQuery != null && siteQuery.Count() > 0)
                    {
                        ProdProcSite ppSite = siteQuery.First();
                        MesLog tmpLog = new MesLog();
                        tmpLog.TableName = "pp_site";
                        tmpLog.TableID = ppSite.ID;
                        tmpLog.BeforeData = EntityTools.GetPropNameAndValue(ppSite);
                        tmpLog.AfterData = "";
                        tmpLog.ChangeType = "delete";
                        tmpLog.ChangeUser = LoginFrm.LoginUser.user_name;
                        tmpLog.ChangeDate = DateTime.Now;
                        ctx.MesLogs.Add(tmpLog);

                        ctx.Entry<ProdProcSite>(ppSite).State = System.Data.Entity.EntityState.Deleted;
                    }

                    var ppQuery = ctx.TargetProdProcesses.Where(p => p.ID == targetID);
                    if (ppQuery != null && ppQuery.Count() > 0)
                    {
                        TargetProdProcess tmpBean = ppQuery.First();
                        MesLog tmpLog = new MesLog();
                        tmpLog.TableName = "target_prod_process";
                        tmpLog.TableID = tmpBean.ID;
                        tmpLog.BeforeData = EntityTools.GetPropNameAndValue(tmpBean);
                        tmpLog.AfterData = "";
                        tmpLog.ChangeType = "delete";
                        tmpLog.ChangeUser = LoginFrm.LoginUser.user_name;
                        tmpLog.ChangeDate = DateTime.Now;
                        ctx.MesLogs.Add(tmpLog);

                        ctx.Entry<TargetProdProcess>(tmpBean).State = System.Data.Entity.EntityState.Deleted;
                    }
                    count = ctx.SaveChanges();
                }
            }
            return count;
        }


        public List<TargetProdProcessDTO> SearchTargetProdForCondition(string prod, string mto, string mo, List<int> siteIds)
        {
            List<TargetProdProcessDTO> resList = new List<TargetProdProcessDTO>();
            using (MesDB ctx = new MesDB())
            {
                ctx.Database.CommandTimeout = 60;
                var query = from a in ctx.TargetProdProcesses
                            join b in ctx.ProdProcScans on a.ID equals b.ProdProcID into res1
                            from ab in res1.DefaultIfEmpty()
                            where a.ProdStatusID != 6
                            select new { A = a,AB = ab };
                if (prod != null && prod.Trim().Length > 0)
                {
                    query = query.Where(t => t.A.ProdNumber.Contains(prod));
                }
                if (mto != null && mto.Trim().Length > 0)
                {
                    query = query.Where(t => t.A.MtoNumber.Contains(mto));
                }
                if (mo != null && mo.Trim().Length > 0)
                {
                    query = query.Where(t => t.A.MoNumber.Contains(mo));
                }
                if (siteIds != null && siteIds.Count > 0)
                {
                    query = query.Where(t => siteIds.Contains(t.A.CurrSiteID));
                }

                if (query != null && query.Count() > 0)
                {
                    foreach (var item in query.Select(t => t.A).Distinct())
                    {
                        TargetProdProcessDTO tarBean = new TargetProdProcessDTO();
                        EntityTools.CopyEntity<TargetProdProcess, TargetProdProcessDTO>(item, ref tarBean);

                        var scanQuery = query.Select(t => t.AB).Where(s => s != null && s.ProdNumber == tarBean.ProdNumber).OrderBy(s => s.ScanDate);
                        if (scanQuery != null && scanQuery.Count() > 0)
                        {
                            tarBean.scanList = new List<ProdProcScan>();
                            tarBean.scanList.AddRange(scanQuery.ToList<ProdProcScan>());
                        }

                        resList.Add(tarBean);
                    }
                }
            }
            return resList;
        }
    }
}
